package jgs1904.config;


import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import jgs1904.matcher.RetryLimitHashedCredentialsMatcher;
import jgs1904.realm.MyRealm;
import jgs1904.realm.MyRealm2;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.io.ResourceUtils;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;
import java.io.InputStream;

@Configuration
public class ShiroConfig {

    // 声明自定义MyRealm的属性
    @Autowired
    private MyRealm myRealm;

    @Autowired
    private MyRealm2 myRealm2;

    /**
     * 声明自定义的匹配器
     */
    @Autowired
    private RetryLimitHashedCredentialsMatcher retryLimitHashedCredentialsMatcher;


    /**
     * 编写SecurityManager的bean配置方法
     * 注意:
     * SpringBoot项目启动的时候会自动的加载配置类的资源，并
     * 将bean方法配置的资源完成初始化设置然后放到Spring容器中
     * 相当于我们之前的bean标签的配置
     */
    @Bean
    protected DefaultWebSecurityManager defaultWebSecurityManager() {
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();

        // 设置登录认证开启MD5加密
        // HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        // matcher.setHashAlgorithmName("md5");
        // matcher.setHashIterations(2);
        // myRealm.setCredentialsMatcher(matcher);
        // 使用自定义matcher
        retryLimitHashedCredentialsMatcher.setHashAlgorithmName("md5");
        retryLimitHashedCredentialsMatcher.setHashIterations(2);
        myRealm.setCredentialsMatcher(retryLimitHashedCredentialsMatcher);

        // 将自定义的realm集成到DefaultWebSecurityManager对象中
        defaultWebSecurityManager.setRealm(myRealm);

        // 设置Shiro的remember me功能
        defaultWebSecurityManager.setRememberMeManager(rememberMeManager());

        // 设置 Shiro和EhCache整合
        defaultWebSecurityManager.setCacheManager(getEhCacheManager());

        return defaultWebSecurityManager;
    }


    /**
     * 设置RememberMeManager对象
     */
    public CookieRememberMeManager rememberMeManager() {
        // 创建CookieRememberMeManager对象
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        // 1.设置Cookie的参数(Cookie的有效期等)
        cookieRememberMeManager.setCookie(rememberMeCookie());
        // 2.对Cookie信息进行加密设置
        cookieRememberMeManager.setCipherKey("1234567890987654".getBytes());
        // 返回
        return cookieRememberMeManager;
    }

    /**
     * 设置Cookie信息
     * new SimpleCookie("rememberMe")      创建一个名为 rememberMe 的 Cookie
     * setPath("/")      整个应用都可访问该 Cookie
     * setHttpOnly(true)      防止 XSS 攻击
     * setMaxAge(...)      设置 Cookie 的有效时间（30 天）
     */
    public SimpleCookie rememberMeCookie() {
        SimpleCookie cookie = new SimpleCookie("rememberMe");
        cookie.setPath("/");
        cookie.setHttpOnly(true);
        cookie.setMaxAge(30 * 24 * 60 * 60);
        return cookie;
    }


    /**
     * 多个Realm认证策略
     *
     * @return
     */
    // @Bean
    // public DefaultWebSecurityManager defaultWebSecurityManager() {
    //
    //     DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    //     ModularRealmAuthenticator modularRealmAuthenticator = new ModularRealmAuthenticator();
    //
    //     // allsuccessfulstrateay 所有realm成功，认证才视为成功
    //     // modularRealmAuthenticator.setAuthenticationStrategy(new AllSuccessfulStrategy());
    //     // atleastonesuccessfulstrategy 只要有一个（或更多）的realm验证成功，那么认证将被视为成功
    //     modularRealmAuthenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
    //
    //     // firstsuccessfulstrateay 第一个realm验证成功，整体认证将被视为成功，且后续realm将被忽略
    //     // modularRealmAuthenticator.setAuthenticationStrategy(new FirstSuccessfulStrategy());
    //     securityManager.setAuthenticator(modularRealmAuthenticator);
    //
    //     // 设置登录认证开启MD5加密
    //     HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
    //     matcher.setHashAlgorithmName("md5");
    //     matcher.setHashIterations(2);
    //     myRealm.setCredentialsMatcher(matcher);
    //
    //     List<Realm> list = new ArrayList<>();
    //     list.add(myRealm);
    //     list.add(myRealm2);
    //     securityManager.setRealms(list);
    //     return securityManager;
    // }


    /**
     * Shiro和EhCache整合
     *
     * @return
     */
    @Bean
    public EhCacheManager getEhCacheManager() {
        EhCacheManager ehCacheManager = new EhCacheManager();
        InputStream is = null;
        try {
            is = ResourceUtils.getInputStreamForPath("classpath:ehcache/ehcache-shiro.xml");
        } catch (IOException e) {
            e.printStackTrace();
        }
        net.sf.ehcache.CacheManager cacheManager = new net.sf.ehcache.CacheManager(is);
        ehCacheManager.setCacheManager(cacheManager);
        return ehCacheManager;
    }


    /**
     * 配置Shiro的内置过滤器
     */
    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition definition = new DefaultShiroFilterChainDefinition();
        // 放行登录页面请求路径
        definition.addPathDefinition("/login", "anon");
        definition.addPathDefinition("/userLogin", "anon");
        definition.addPathDefinition("/logout", "logout");
        definition.addPathDefinition("/**", "user");
        return definition;
    }


    /**
     * 配置页面的shiro标识的解析bean
     */
    @Bean
    public ShiroDialect shiroDialect() {
        return new ShiroDialect();
    }


}
